package jplat.core.session.redis;

import java.io.IOException;
import java.util.Map;

import jplat.base.constant.KConfigKeys;
import jplat.base.constant.KJPlatBase;
import jplat.base.constant.KTraceLog;
import jplat.error.exception.JSystemException;
import jplat.tools.coder.JsonCoder;
import jplat.tools.config.JDataBaseConfig;
import jplat.tools.config.JLogConfig;
import jplat.tools.string.JLogUtils;
import jplat.tools.string.JRandomUtil;
import jplat.tools.string.StringUtil;
import jplat.tools.string.XLog;

import org.apache.log4j.Logger;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;

public class JRedisConnector
{
	public static long FAIL = -1;		//失败。

	public static long EX_NEW = 1;		//新值.
	public static long EX_OLD = 0;		//老值.
	public String password;

	private static Logger logger = Logger.getLogger(JRedisConnector.class);

	private JedisPool redisPool;

	private JRedisConnector()
	{
		//这里还是依赖了Spring哦.
		//		QConfig qconfig = AppContextHolder.getContext().getBean(QConfig.class);

		String server = null;
		int port=0,maxConn=0,minIdle=0, maxWaitMills=0,timeout=0;

		try
		{
			JDataBaseConfig proReader = JDataBaseConfig.getInstance();

			server = proReader.getString(KConfigKeys.REDIS_SERVER,true);
			port = proReader.getInt(KConfigKeys.REDIS_PORT,true);
			timeout = proReader.getInt(KConfigKeys.REDIS_CONNECT_TIME_OUT,true);	

			maxWaitMills = proReader.getInt(KConfigKeys.REDIS_MAX_WAIT_MILLIS,true);
			maxConn = proReader.getInt(KConfigKeys.REDIS_MAX_CONNECT,true);
			minIdle = proReader.getInt(KConfigKeys.REDIS_MIN_IDLE,true);
			password = proReader.getString(KConfigKeys.REDIS_PASSWORD, null);
		}
		catch( JSystemException e )
		{
			e.printStackTrace();
			return;
		}

		JedisPoolConfig config = new JedisPoolConfig();
		//		config.setBlockWhenExhausted(true);
		config.setMaxTotal(maxConn);
		config.setMinIdle(minIdle);
		config.setMaxWaitMillis(maxWaitMills);

		//5000ms超时是可以，默认是2000
		redisPool = new JedisPool(config,server,port,timeout);

		XLog.log(JLogUtils.getTraceLog(KTraceLog.ACTION_JINIT, KTraceLog.EVENT_SUCCESS, "",
				JLogUtils.buildUserData("REDIS_POOL_INIT",server,""+port,password,""+timeout,JsonCoder.toJsonString(config))));
	}

	private static final class Holder
	{
		private static final JRedisConnector  connector = new JRedisConnector();
	}

	public static JRedisConnector getInstance()
	{
		return Holder.connector;
	}

	//---------------getter-settter-operations--------------

	/**
	 * 设置值
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean set( String key, String value )
	{
		Jedis jedis = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			String retMsg = jedis.set(key, value);
			if ( !KJPlatBase.REDIS_RET_OK.equals(retMsg))
			{
				return false;
			}
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}
		finally
		{
			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return true;
	}

	/**
	 * 获取值.
	 * @param key
	 * @param value
	 * @return
	 */
	public String get( String key )
	{
		Jedis jedis = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			return jedis.get(key);
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}
		finally
		{
			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return null;
	}

	/**
	 * 删除.
	 * @author zhangcq
	 * @date Jan 6, 2017
	 * @comment 
	 * @param key
	 * @return
	 */
	public long del( String key )
	{
		Jedis jedis = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			long ret = jedis.del(key);

			return ret;
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}
		finally
		{
			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return FAIL;
	}

	/**
	 * 设置值并超时时间.
	 * @param key
	 * @param value
	 * @param timeOutSec
	 * @return
	 */
	public boolean set( String key, String value, int timeOutSec )
	{
		boolean success = true;
		String mark = JRandomUtil.getRandomSequence(KTraceLog.MARK_LENGTH);
		if ( JLogConfig.REDIS_LOG_ON )
		{
			logger.info(JLogUtils.getStartTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("set",key) ));
		}
		
		Jedis jedis = null;
		Pipeline pl = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			pl = jedis.pipelined();
			Response<String> response = pl.set(key, value);
			pl.expire(key, timeOutSec );
			pl.sync();

			//			pl.close();
			//			jedis.close();
			if ( !KJPlatBase.REDIS_RET_OK.equals(response.get()))
			{
				success = false;
				return false;
			}
		}
		catch ( Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			success = false;
		}
		finally
		{
			if ( JLogConfig.REDIS_LOG_ON )
			{
				logger.info(JLogUtils.getEndTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("set",key,""+success) ));
			}
			
			if ( pl != null )
			{
				try {
					pl.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return true;
	}

	/**
	 * 返回值并更新超时时间.
	 * @param key
	 * @param value
	 * @param timeOutSec
	 * @return
	 */
	public String get( String key, int timeOutSec )
	{
		boolean success = true;
		String mark = JRandomUtil.getRandomSequence(KTraceLog.MARK_LENGTH);
		if ( JLogConfig.REDIS_LOG_ON )
		{
			logger.info(JLogUtils.getStartTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("get",key) ));
		}
		
		Jedis jedis = null;
		Pipeline pl = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			pl = jedis.pipelined();
			Response<String> response = pl.get(key);
			pl.expire(key, timeOutSec );
			pl.sync();
			//		pl.close();
			//		jedis.close();

			return response.get();
		}
		catch ( Exception e)
		{
			success=false;
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally
		{
			if ( JLogConfig.REDIS_LOG_ON )
			{
				logger.info(JLogUtils.getEndTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("get",key,""+success) ));
			}
			
			if ( pl != null )
			{
				try {
					pl.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return null;
	}

	/******
	 ********************  Redis的HSET/HGET. ************************
	 */

	/***
	 * hset方法.
	 * @param key
	 * @param field
	 * @param value
	 * @return 0-覆盖旧域名.1-产生新域.
	 */
	public long hset( String key, String field, String value )
	{
		Jedis jedis = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			long retl = jedis.hset(key,field,value);
			//		jedis.close();
			return retl;
		}
		catch ( Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally
		{
			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return FAIL;
	}

	/***
	 * 获取值.
	 */
	public String hget( String key, String field )
	{
		Jedis jedis = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			String retstr = jedis.hget(key,field);
//			jedis.close();

			return retstr;
		}
		catch ( Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally
		{
			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return null;
	}

	/***
	 * hset方法.
	 * @param key
	 * @param field
	 * @param value
	 * @param timeout
	 * @return 0-覆盖旧域名.1-产生新域.
	 */
	public long hset( String key, String field, String value, int timeout )
	{
		boolean success = true;
		String mark = JRandomUtil.getRandomSequence(KTraceLog.MARK_LENGTH);
		if ( JLogConfig.REDIS_LOG_ON )
		{
			logger.info(JLogUtils.getStartTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("hset",key,field) ));
		}
		
		Jedis jedis = null;
		Pipeline pl = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			pl = jedis.pipelined();
			Response<Long> response = pl.hset(key,field,value);
			pl.expire(key, timeout );
			pl.sync();

//			pl.close();
//			jedis.close();
			
			return response.get();
		}
		catch ( Exception e)
		{
			success=false;
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally
		{
			if ( JLogConfig.REDIS_LOG_ON )
			{
				logger.info(JLogUtils.getEndTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("hset",key,field,""+success) ));
			}
			
			if ( pl != null )
			{
				try {
					pl.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return FAIL;
	}

	/***
	 * hset方法.
	 * @param key
	 * @param field
	 * @param value
	 * @param timeout
	 * @return 0-覆盖旧域名.1-产生新域.
	 */
	public void hset( String key, Map<String,String> sessMap, int timeout )
	{
		boolean success = true;
		String mark = JRandomUtil.getRandomSequence(KTraceLog.MARK_LENGTH);
		if ( JLogConfig.REDIS_LOG_ON )
		{
			logger.info(JLogUtils.getStartTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("hset.maps",key) ));
		}
		
		Jedis jedis = null;
		Pipeline pl = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			pl = jedis.pipelined();
			for ( String tmpKey : sessMap.keySet() )
			{
				Response<Long> response = pl.hset(key,tmpKey,sessMap.get(tmpKey));
			}

			pl.expire(key, timeout );
			pl.sync();
			//			pl.close();
			//			jedis.close();

		}
		catch ( Exception e)
		{
			success=false;
			// TODO Auto-generated catch block
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		finally
		{
			if ( JLogConfig.REDIS_LOG_ON )
			{
				logger.info(JLogUtils.getEndTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("hset.maps",key,""+success) ));
			}
			
			if ( pl != null )
			{
				try {
					pl.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			if ( jedis != null )
			{
				jedis.close();
			}
		}
	}

	/***
	 * 获取值.
	 */
	public String hget( String key, String field, int timeout )
	{
		boolean success = true;
		String mark = JRandomUtil.getRandomSequence(KTraceLog.MARK_LENGTH);
		if ( JLogConfig.REDIS_LOG_ON )
		{
			logger.info(JLogUtils.getStartTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("hget",key,field) ));
		}
		
		Jedis jedis = null;
		Pipeline pl = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			pl = jedis.pipelined();
			Response<String> response = pl.hget(key,field);		//response 是否会为空.
			pl.expire(key, timeout );
			pl.sync();
			
//			pl.close();
//			jedis.close();

			return response.get();
		}
		catch ( Exception e)
		{
			success=false;
			logger.error(e.getMessage());
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally
		{
			if ( JLogConfig.REDIS_LOG_ON )
			{
				logger.info(JLogUtils.getEndTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("hget",key,field,""+success) ));
			}
			
			if ( pl != null )
			{
				try {
					pl.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return null;
	}

	/**
	 * 按照域删除.
	 * @author zhangcq
	 * @date Jan 6, 2017
	 * @comment 
	 * @param key
	 * @param field
	 * @return
	 */
	public long hdel( String key , String field )
	{
		boolean success = true;
		String mark = JRandomUtil.getRandomSequence(KTraceLog.MARK_LENGTH);
		if ( JLogConfig.REDIS_LOG_ON )
		{
			logger.info(JLogUtils.getStartTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("hdel",key,field) ));
		}
		
		Jedis jedis = null;
		try
		{
			jedis = redisPool.getResource();
			if ( StringUtil.isNotEmpty(password) )
			{
				jedis.auth(password);
			}

			long ret = jedis.del(key,field);
			return ret;
		}
		catch ( Exception e)
		{
			// TODO Auto-generated catch block
			success=false;
			e.printStackTrace();
		}
		finally
		{
			if ( JLogConfig.REDIS_LOG_ON )
			{
				logger.info(JLogUtils.getEndTraceLog(KTraceLog.ACTION_REDIS, mark, JLogUtils.buildUserData("hdel",key,field,""+success) ));
			}
			
			if ( jedis != null )
			{
				jedis.close();
			}
		}

		return FAIL;
	}

	/******** FIHISH *************/

	public static void main(String[] args) throws JSystemException
	{
		JRedisConnector connector = JRedisConnector.getInstance();
		connector.testRedis2();
	}

	private void testRedis2() throws JSystemException
	{
		JRedisSession redisSession = new JRedisSession();

		redisSession = new JRedisSession(redisSession.getSessionID());
		//XLog.log("__SESSION_ID:"+redisSession.getSessionID());

		//redisSession.setValue("user_name", "Jimmy");
		redisSession.setValue("ch_name", "吉米");

//		AppUserAuthReqModel model = new AppUserAuthReqModel();
//		model.setAppVersion("69");
//
//		model.setAuthKey("abbbbbdsfbdf");
//		model.setAuthType("令牌认证");
//		redisSession.setObj("obj0",  model);
//
//		model = (AppUserAuthReqModel)redisSession.getObj("obj0");
//
//		XLog.log("authKey=%s,authType=%s,version=%s", model.getAuthKey(),model.getAuthType(),model.getAppVersion());
	}

	private void testRedis1()
	{
		Jedis jedis = new Jedis("162.16.2.152", 6379);

		//权限认证
		jedis.auth("push-redis"); 
	}

	private void testRedis0()
	{

		String sendMsg = "{\"custNo\":\"00000013162\",\"custName\":\"凌欢\",\"idtype\":\"01\",\"idNo\":\"632324198303056355\",\"level\":\"2\",\"mobileNo\":\"13498741236\",\"gender\":\"M\",\"loginTime\":\"Jul 22, 2016 10:22:28 PM\",\"loginType\":\"M\",\"vipLevel\":\"0\",\"state\":\"0\",\"binddevice\":true,\"secListNum\":\"\",\"cardList\":[{\"cardNo\":\"6214461111000009082\",\"cardType\":\"BCSEBANK\",\"cardId\":\"N8200\",\"bankNo\":\"\",\"bankName\":\"长沙银行e账户\",\"mobileNo\":\"13498741236\",\"prodName\":\"\",\"accountName\":\"凌欢\",\"state\":\"0\",\"mark\":\"0\",\"nickName\":\"\"},{\"cardNo\":\"6223687310873691173\",\"cardType\":\"BCS\",\"cardId\":\"N7301\",\"bankNo\":\"013601\",\"bankName\":\"长沙银行借记卡\",\"mobileNo\":\"13498741236\",\"prodName\":\"\",\"accountName\":\"凌欢\",\"state\":\"0\",\"mark\":\"0\",\"nickName\":\"\"}],\"secToolList\":[]}";

		JRedisConnector connector = JRedisConnector.getInstance();

		XLog.log("use-redis-password:[%s]", connector.password);

		String ss = connector.get("__T");
		XLog.log("ss.ss="+ss);
		for ( int i=0; i < 9; ++i )
		{
			String key = "9988";
			connector.set(key, sendMsg);

			int j = i;
			if (i%4==0)
			{
				j = i-1;
			}
			long retl = connector.hset("key"+j, "field"+j, "value"+j, 120 );
			XLog.log("hset.ret="+retl);

			String rets = connector.hget("key"+j, "field"+j, 120 );
			XLog.log("hget.ret="+rets);
		}

	}
}
